<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <title>Jessibuca Pro 回放流 demo</title>
    <script src="./vconsole.js"></script>
    <script src="./js/jessibuca-pro-demo.js"></script>
    <link rel="stylesheet" href="./demo.css">
    <style>
        .container-shell:before {
            content: "jessibuca pro 回放流 demo";
        }
    </style>
</head>
<body class="page">
<div class="root">
    <div class="container-shell">
        <div id="container"></div>
        <div class="input">
            <div>
                当前浏览器：
                <span id="mseSupport264" style="color: green;display: none">支持MSE H264解码；</span>
                <span id="mseSupport" style="color: green;display: none">支持MSE H265解码；</span>
                <span id="mseNotSupport264" style="color: red;display: none">不支持MSE H264解码；</span>
                <span id="mseNotSupport"
                      style="color: red;display: none">不支持MSE H265解码,会自动切换成wasm解码；</span>
            </div>
        </div>
        <div class="input">
            <div>
                当前浏览器：
                <span id="wcsSupport264" style="color: green;display: none">支持Webcodecs H264解码；</span>
                <span id="wcsSupport" style="color: green;display: none">支持Webcodecs H265解码（不一定准确）；</span>
                <span id="wcsNotSupport264"
                      style="color: red;display: none">不支持Webcodecs H264解码(https/localhost)；</span>
                <span id="wcsNotSupport" style="color: red;display: none">不支持Webcodecs H265解码(https/localhost),会自动切换成wasm解码</span>
            </div>
        </div>
        <div class="input">
            <div>
                当前浏览器：
                <span id="wasmSupport" style="color: green;display: none">支持WASM解码；</span>
                <span id="simdSupport" style="color: green;display: none">支持WASM SIMD解码</span>
                <span id="simdMtSupport" style="color: green;display: none">支持WASM WASM(SIMD) 多线程解码；</span>
                <span id="wasmNotSupport" style="color: red;display: none">不支持WASM解码</span>
                <span id="simdNotSupport"
                      style="color: red;display: none">不支持WASM SIMD解码,会自动切换成wasm解码</span>
                <span id="simdMtNotSupport" style="color: red;display: none">不支持WASM WASM(SIMD) 多线程解码；</span>

            </div>
        </div>

        <div class="input">
            <div>
                <span><span style="color: red">TPS:动态(根据流):</span>播放器的倍率播放完全是根据服务器端推流的速率，如果服务器端推的是一倍率且动态码率的流，
                播放器就按照一倍率动态码率渲染。<span style="color: green">例如 fps会15到30之间跳动 。</span> <span
                        style="color: red">（画面会看着卡顿）</span>
            </span>
            </div>
        </div>
        <div class="input">
            <div>
                <span><span style="color: red">TPS:定频（本地设置）:</span>播放器端会提前缓存数据，然后根据流数据计算出fps，不会随着流的速率变化而变化。
                支持设置播放器的播放倍率（提高渲染倍率）。<span
                        style="color: green">在推流码率足够的情况下，播放器会按照固定倍率播放</span>
            </span>
            </div>
        </div>
        <div class="input">
            <div>
                <span><span style="color: red">TPS:解码前缓冲数据:</span>对于存在有些流会一下子以2倍甚至4倍的速率推送的情况，如果设置为true，则会根据计算出来的fps，只根据fps和倍率来解码数据，其他数据还是被缓存在队列中，等待解码。
            </span>
            </div>
        </div>
        <div class="input">
            <div>
                <span><span style="color: red">TPS:服务器端倍率推流:</span> 如果服务器端按照倍率推流，播放器端也需要同步的以倍率播放【调用forward(rate)】接口
            </span>
            </div>
        </div>

        <div class="input">
            <div>
                <div>
                    <span>硬解码：</span>
                    <input
                        type="checkbox"
                        checked
                        id="useMSE"
                    /><span>MediaSource</span>
                    <input
                        type="checkbox"
                        id="useWCS"
                    /><span>Webcodec</span>
                </div>
                <div>
                    <span>软解码：</span>
                    <input
                        type="checkbox"
                        id="useSIMD"
                    /><span>WASM(SIMD)</span>
                    <input
                        type="checkbox" ,
                        id="isFFmpegSIMD"
                        onclick="replay()"
                    /><span>isSIMD(V2)</span>
                    <input
                        type="checkbox"
                        checked
                        id="useSIMDMThreading"
                        onclick="replay()"
                    /><span>启动多线程（WASM,WASM(SIMD)解码支持）</span>
                </div>
            </div>

        </div>
        <div class="input">
            <div class="playbackForward">
                <span>FPS设置：</span>
                <select id="isUseFpsRender" style="width: 140px">
                    <option value="false" selected>动态(根据流)</option>
                    <option value="true">定频（本地设置）</option>
                </select>
            </div>
        </div>
        <div class="input">
            <span>是否显示操作按钮</span>
            <select id="isShowControl" style="width: 50px">
                <option value="true" selected>是</option>
                <option value="false">否</option>
            </select>
        </div>
        <div class="input">
            <span>是否显示时间轴</span>
            <select id="isShow24H" style="width: 50px">
                <option value="true" selected>是</option>
                <option value="false">否</option>
            </select>
        </div>
        <div class="input">
            <span>只解码I帧(<span style="color:red;">点击重播按钮生效</span>)</span>
            <select id="onlyDecoderIFrame" style="width: 50px">
                <option value="1">1倍</option>
                <option value="2">2倍</option>
                <option value="4" selected>4倍</option>
                <option value="8">8倍</option>
            </select>
        </div>
        <div class="input">
            <div>
                <span>不断流暂停是否清除缓存数据</span>
                <select id="isPlaybackPauseClearCache" style="width: 50px">
                    <option value="true" selected>是</option>
                    <option value="false">否</option>
                </select>
            </div>
        </div>
        <div class="input">
            <span>ui是否使用playbackPause</span>
            <select id="uiUsePlaybackPause" style="width: 50px">
                <option value="true">是</option>
                <option value="false" selected>否</option>
            </select>
        </div>
        <div class="input">
            <span>canvas渲染技术：</span>
            <select id="isUseWebGPU" onchange="replay()">
                <option value="webgl" selected>webgl</option>
                <option value="webgpu">webgpu</option>
            </select>
            <span id="supportWebgpu"></span>
        </div>
        <div class="input">
            <div>
                <span>进度条时长(单位：秒)</span>
                <input id="playbackDuration" style="width: 100px" type="text" placeholder="单位秒" value="600">秒(例如十分钟：10*
                60 = 600)
            </div>
        </div>
        <div class="input">
            <span>是否检测流结束：</span>
            <select id="playbackCheckStreamEnd" style="width: 50px">
                <option value="true" selected>是</option>
                <option value="false">否</option>
            </select>
            <span>(如果检测流结束，会抛出streamEnd异常，否的话，则会渲染完所有数据抛出playbackEnd事件)</span>
        </div>
        <div class="input">
            <button onclick="replay()">重播</button>
        </div>
        <div class="input">
            <div>输入URL：</div>
            <input
                autocomplete="on"
                id="playUrl"
                value=""
            />
        </div>
        <div class="input">
            <button id="play">播放</button>
            <button id="pause">停止(流会断开)</button>
            <button id="playbackPause">停止(流不断开)</button>
        </div>
        <div class="input" style="line-height: 30px">
            <button id="destroy">销毁</button>
        </div>
    </div>
</div>
<script src="./demo.js"></script>

<script>
    var $player = document.getElementById('play');
    var $pause = document.getElementById('pause');
    var $playbackPause = document.getElementById('playbackPause');
    var $playHref = document.getElementById('playUrl');
    var $container = document.getElementById('container');
    var $destroy = document.getElementById('destroy');
    var $isUseFpsRender = document.getElementById('isUseFpsRender');
    var $isShowControl = document.getElementById('isShowControl'); // 是否显示按钮
    var $isShow24H = document.getElementById('isShow24H'); // 是否显示操作栏
    var $onlyDecoderIFrame = document.getElementById('onlyDecoderIFrame');
    var $isPlaybackPauseClearCache = document.getElementById('isPlaybackPauseClearCache');
    var $uiUsePlaybackPause = document.getElementById('uiUsePlaybackPause');
    var $supportWebgpu = document.getElementById('supportWebgpu');
    var $isUseWebGPU = document.getElementById('isUseWebGPU');
    var $playbackDuration = document.getElementById('playbackDuration');
    var $useMSE = document.getElementById('useMSE');
    var $useSIMD = document.getElementById('useSIMD');
    var $isFFmpegSIMD = document.getElementById('isFFmpegSIMD');
    var $useWCS = document.getElementById('useWCS');
    var $playbackCheckStreamEnd = document.getElementById('playbackCheckStreamEnd');
    var $useSIMDMThreading = document.getElementById('useSIMDMThreading');


    var forceNoOffscreen = true; //
    var jessibuca = null;
    var isPlaybackPause = false;
    var $isUseWebGPU = document.getElementById('isUseWebGPU');

    var isSupportWebgpu = 'gpu' in navigator;

    if (isSupportWebgpu) {
        $supportWebgpu.style.color = 'green';
        $supportWebgpu.innerHTML = '支持webGPU';
    } else {
        $supportWebgpu.style.color = 'red';
        $supportWebgpu.innerHTML = '暂不支持webGPU，降级到webgl渲染';
    }

    function create() {
        const showOperateBtns = $isShowControl.value === 'true';
        const onlyDecoderIFrame = Number($onlyDecoderIFrame.value);
        var isUseFpsRender = $isUseFpsRender.value;
        const isShow24H = $isShow24H.value === 'true';
        jessibuca = new JessibucaPro({
            playType: 'playbackTF',
            container: $container,
            videoBuffer: 0.2, // 缓存时长
            decoder: './js/decoder-pro.js',
            isResize: false,
            text: "",
            loadingText: "加载中",
            debug: true,
            debugLevel: 'debug',
            showPerformance: true,
            isFFmpegSIMD: $isFFmpegSIMD.checked,
            useMThreading: $useSIMDMThreading.checked === true,
            showBandwidth: showOperateBtns, // 显示网速
            showPlaybackOperate: showOperateBtns,
            operateBtns: {
                fullscreen: showOperateBtns,
                screenshot: showOperateBtns,
                play: showOperateBtns,
                audio: showOperateBtns,
                zoom: showOperateBtns,
                performance: showOperateBtns,
            },
            playbackConfig: {
                controlType: 'simple',
                duration: Number($playbackDuration.value),
                showControl: isShow24H,
                isUseFpsRender: isUseFpsRender === 'true',
                isCacheBeforeDecodeForFpsRender: isUseFpsRender === 'true',
                showRateBtn: true,
                supportWheel: true,
                uiUsePlaybackPause: $uiUsePlaybackPause.value === 'true',
                isPlaybackPauseClearCache: $isPlaybackPauseClearCache.value === 'true',
                rateConfig: [
                    {label: '正常', value: 1},
                    {label: '2倍', value: 2},
                    {label: '4倍', value: 4},
                    {label: '8倍', value: 8},
                    {label: '16倍', value: 16},
                ],
                useWCS: $useWCS.checked,
                useMSE: $useMSE.checked,
                useSIMD: $useSIMD.checked,
            },
            forceNoOffscreen: forceNoOffscreen,
            isNotMute: false,
            playbackForwardMaxRateDecodeIFrame: onlyDecoderIFrame,
            useWebGPU: $isUseWebGPU.value === 'webgpu', // 使用WebGPU
            playbackCheckStreamEnd: $playbackCheckStreamEnd.value === 'true',
        },);

        $player.style.display = 'inline-block';
        $pause.style.display = 'none';
        $playbackPause.style.display = 'none';
        $destroy.style.display = 'none';


        jessibuca.on('playbackPreRateChange', (rate) => {
            jessibuca.forward(rate);
        })

        jessibuca.on('playbackSeek', (data) => {
            jessibuca.setPlaybackStartTime(data.ts);
        })

        jessibuca.on('playbackEnd', () => {
            console.error('playbackEnd: 播放结束');
        })


        jessibuca.on(JessibucaPro.EVENTS.playFailedAndPaused, (error) => {
            jessibuca.showErrorMessageTips('播放异常：' + error);
        })

    }


    create();

    function replay() {
        if (jessibuca) {
            jessibuca.destroy().then(() => {
                create();
                play();
            });
        } else {
            create();
            play();
        }
    }

    function play() {
        var href = $playHref.value;


        if (!href) {
            return
        }

        if (isPlaybackPause) {
            jessibuca.playbackResume()
        } else {
            jessibuca.playback(href).then(() => {
                notifySuccess('播放成功');

            }).catch((error) => {
                jessibuca.showErrorMessageTips('播放异常：' + error);
            });
        }
        isPlaybackPause = false;
        $player.style.display = 'none';
        $pause.style.display = 'inline-block';
        $playbackPause.style.display = 'inline-block';
        $destroy.style.display = 'inline-block';
    }


    $player.addEventListener('click', function () {
        play();
    }, false)


    $pause.addEventListener('click', function () {
        $player.style.display = 'inline-block';
        $pause.style.display = 'none';
        $playbackPause.style.display = 'none';
        jessibuca.pause();
    })

    $useMSE.addEventListener('click', function () {
        const checked = $useMSE.checked;
        if (checked) {
            $useSIMD.checked = false
            $useWCS.checked = false
        }
        replay();
    })

    $useSIMD.addEventListener('click', function () {
        const checked = $useSIMD.checked;
        if (checked) {
            $useMSE.checked = false
            $useWCS.checked = false
        }
        replay();
    })

    $useWCS.addEventListener('click', function () {
        const checked = $useWCS.checked;
        if (checked) {
            $useMSE.checked = false
            $useSIMD.checked = false
        }
        replay();
    })


    $playbackPause.addEventListener('click', function () {
        $playbackPause.style.display = 'none';
        $pause.style.display = 'none';
        $player.style.display = 'inline-block';
        jessibuca.playbackPause();
        isPlaybackPause = true;
    })

    $destroy.addEventListener('click', function () {
        if (jessibuca) {
            jessibuca.destroy().then(() => {
                create();
            });
        } else {
            create();
        }

    })

    function currentTimeScroll() {
        if (jessibuca) {
            jessibuca.playbackCurrentTimeScroll();
        }
    }


</script>

</body>
</html>
